﻿using System;
using System.Collections.Generic;
using System.Collections;
using System.Linq;
using System.Text;
using Qas.CommonLogic;
using Qas.CommonLogic.BusinessObjects;
using System.Windows.Forms;

namespace Qas.CommonLogic.Business_Objects.Graph
{
    public class State
    {
        private List<Condition> conditionsField = new List<Condition>();
        private double weightField = 0;
        private State previousStateField;
        private List<Task> visitedTasks = new List<Task>();

        //PriorityQueue 

        public override string ToString()
        {
            string result = "State:";
            foreach (Condition condItem in this.Conditions)
            {
                result += condItem.ID.ToString() + "-";
            }

            return result;
        }

        public State(State state)
        {
            if (state == null)
            {
                throw new NullReferenceException();
            }
            else
            {
                this.previousState = state.previousState;
                this.visitedTasks = state.visitedTasks;
                this.Weight = state.Weight;
                this.Conditions = state.Conditions;
            }
        }

        public State()
        {
        }

        public State(List<Condition> conditions, double weight, State prevState, List<Task> tasks)
        {
            this.Conditions = conditions;

            if ((Weight == 0) || (weight < Weight))
            {
                Weight = weight;
                this.previousState = prevState;
            }

            this.Tasks = tasks;
        }

        public List<Condition> PostConditions()
        {
            if (this.Tasks == null)
            {
                return null;
            }
            else
            {
                List<Condition> postConditions = new List<Condition>();
                foreach (Task task in this.Tasks)
                {
                    postConditions.AddRange(task.PostConditions);
                }
                return postConditions;
            }
        }


        public override bool Equals(object obj)
        {
            State anotherState = obj as State;

            if (anotherState == null)
            {
                throw new NullReferenceException();
            }

            List<Condition> tmp = anotherState.Conditions;

            foreach (Condition cond in this.Conditions)
            {
                if (tmp.Contains(cond))
                {
                    tmp.Remove(cond);
                }
                else
                {
                    return false;
                }
            }

            return (tmp.Count == 0);
        }

        public double Weight
        {
            get
            {
                return this.weightField;
            }
            set
            {
                this.weightField = value;
            }
        }

        public List<Task> Tasks
        {
            get
            {
                return this.visitedTasks;
            }
            set
            {
                this.visitedTasks = value;
            }
        }

        public double Cost()
        {
            if (this.Tasks == null)
            {
                return 0;
            }
            else
            {
                double cost = 0;
                foreach (Task task in this.Tasks)
                {
                    cost += task.PDCost.Expectancy;
                }
                return cost;
            }
        }

        public List<Condition> Conditions
        {
            get
            {
                return this.conditionsField;
            }
            set
            {
                this.conditionsField = value;
            }
        }

        public State previousState
        {
            get
            {
                return this.previousStateField;
            }
            set
            {
                this.previousStateField = value;
            }
        }

        //public Plan getTasks1()
        //{
        //    if (this.Task == null)
        //    {
        //        throw new NullReferenceException();
        //    }
        //    else
        //    {
        //        List<Task> tasks = new List<Task>();
        //        tasks.Add(this.Task);
        //        if (this.previousState.Conditions.Count != 0)
        //        {
        //            State state = new State(this.previousState);


        //            //List<Condition> conditions = new List<Condition>();

        //            while (state.previousState != null)
        //            {
        //                tasks.Add(state.Task);
        //                state = state.previousState;
        //            }
        //        }
        //        tasks.Reverse();


        //        Plan plan = new Plan(tasks);

        //        return plan;
        //    }
        //}

        public Plan getTasks()
        {
            if (this.visitedTasks == null)
            {
                throw new NullReferenceException();
            }
            else
            {
                Plan plan = new Plan();
                foreach (Task task in this.Tasks)
                {
                    plan.AddTask(task);
                }
                return plan;
            }
        }


        public bool ContatinsPreCondition(Task otherTask)
        {
            if (otherTask == null)
            {
                throw new NullReferenceException(); 
            }
            else
            {
                foreach (Task task in this.getTasks().Tasks)
                {
                    if (Condition.Subtraction(otherTask.PreConditions, task.PreConditions).Count == 0)
                    {
                        return true;
                    }
                }
                return false;
            }
        }

        public bool CoversPostConditions(Task otherTask)
        {
            if (otherTask == null)
            {
                throw new NullReferenceException();
            }
            else
            {
                List<Condition> conditions = new List<Condition>();
                foreach (Task task in this.getTasks().Tasks)
                {
                 
                    conditions.AddRange(task.PostConditions);
                }
                    
                if (Condition.Subtraction(otherTask.PreConditions, conditions).Count == 0)
                {
                        return true;
                }
                return false;
            }
        }

        private bool checkTask(Task task, List<Condition> conditions)
        {
            if (task.PreConditions.Count != 0)
            {
                if (Condition.Subtraction(task.PreConditions, conditions).Count == 0)
                {
                    return false;
                }
                else
                {
                    conditions.AddRange(task.PreConditions);
                }
            }
            return true;
        }
    }
}
